<template>
  <public-dialog
          :width="popupParams.width || '50%'"
          :title="popupParams.title || '提示'"
          :footer-button="popupParams.footerButton!==undefined?popupParams.footerButton:true"
          :confirm-button-title="popupParams.confirmButtonTitle"
          :confirm-disabled="isLoading"
          v-model:visible="visible"
          @on-confirm="onConfirm"
  >
   <template #default>
       <el-main
               v-loading="isLoading"
               :element-loading-text="popupParams.loadingText || '加载中...'"
       >
           <el-form
               ref="formRef"
               :model="form"
               :rules="rules"
               :label-width="popupParams.labelWidth===undefined?'150px':popupParams.labelWidth + 'px'"
           >
               <template v-for="(item,index) in fields" :key="index">
                   <!-- 输入类型  input -->
                   <el-form-item
                           v-if="item.type === 'input'"
                           :label="item.label"
                           :label-width="item.labelWidth"
                           :prop="item.key"
                           :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-input
                                v-model="form[item.key]"
                               :style="{width:item.width?item.width + 'px':'100%'}"
                               class="m-l5 input-width"
                               :clearable="item.clearable || false"
                               :disabled="item.disabled || false"
                               :placeholder="item.placeholder"
                               @input="(e)=>{if(item.fun){item.fun(e)}}"
                       ></el-input>
                   </el-form-item>

                   <!-- 输入类型  textarea -->
                   <el-form-item
                           v-if="item.type === 'textarea'"
                           :label="item.label"
                           :label-width="item.labelWidth"
                           :prop="item.key"
                           :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-input
                               v-model="form[item.key]"
                               :style="{width:item.width?item.width + 'px':'100%'}"
                               class="m-l5 input-width"
                               type="textarea"
                               :clearable="item.clearable || false"
                               :disabled="item.disabled || false"
                               :rows="item.rows || 2"
                               :placeholder="item.placeholder"
                               @input="(e)=>{if(item.fun){item.fun(e)}}"
                       ></el-input>
                   </el-form-item>

                   <!-- 下拉类型  select -->
                   <el-form-item
                           v-if="item.type === 'select'"
                           :label="item.label"
                           :label-width="item.labelWidth"
                           :prop="item.key"
                           :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-select
                               class="m-l5"
                               :style="{width:item.width?item.width + 'px':'100%'}"
                               :clearable="item.clearable || false"
                               :disabled="item.disabled || false"
                               :multiple="item.multiple || false"
                               :collapse-tags="item.collapseTags || false"
                               :filterable="item.filterable || false"
                               v-model="form[item.key]"
                               :placeholder="item.placeholder"
                               @change="(e)=>{if(item.fun){item.fun(e)}}"
                       >
                           <el-option
                                   v-for="(subItem, sonIndex) in item.options.list"
                                   :key="sonIndex"
                                   :label="subItem[item.options.labelKey]"
                                   :value="subItem[item.options.valueKey]"
                           />
                       </el-select>
                   </el-form-item>

                   <!-- 时间范围选择 datetimerange -->
                   <el-form-item
                           v-if="item.type === 'datetimerange'"
                           :label="item.label"
                           :label-width="item.labelWidth"
                           :prop="item.key"
                           :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <div class="el-p">
                           <el-date-picker
                               v-model="form[item.key]"
                               :style="{width:item.width?item.width + 'px':'100%'}"
                               :disabled="item.disabled || false"
                               type="datetimerange"
                               class="search_time m-l5"
                               size="large"
                               range-separator="-"
                               start-placeholder="开始时间"
                               end-placeholder="结束时间"
                               :value-format="item.valueFormat ||  'YYYY-MM-DD HH:mm:ss'"
                               @change="(e)=>{if(item.fun){item.fun(e,{startTimeName:item.startTimeName,endTimeName:item.endTimeName})}}"
                           >
                           </el-date-picker>
                       </div>
                   </el-form-item>

                <!-- 日期时间选择器 datetime-->
                   <el-form-item
                       v-if="item.type === 'datetime'"
                       :label="item.label"
                       :label-width="item.labelWidth"
                       :prop="item.key"
                       size="large"
                       :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <div class="el-p">
                           <el-date-picker
                               v-model="form[item.key]"
                               value-format="YYYY-MM-DD HH:mm:ss"
                               type="datetime"
                               :placeholder="item.placeholder || '请选择'"
                           />
                       </div>
                   </el-form-item>

                   <!-- 时间范围选择  year-->
                   <el-form-item
                           v-if="item.type === 'year'"
                           :label="item.label"
                           :label-width="item.labelWidth"
                           :prop="item.key"
                           :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-date-picker
                               v-model="form[item.key]"
                               :style="{'--style-width':item.width?item.width + 'px':'100%'}"
                               class="m-l5 date-picker-year"
                               value-format="YYYY"
                               :disabled="item.disabled || false"
                               type="year"
                               placeholder="请选择"
                               size="large"
                       />
                   </el-form-item>

                   <!-- 级联选择器  -->
                   <el-form-item
                       v-if="item.type==='cascader'"
                       :label="item.label"
                       :label-width="item.labelWidth"
                       :prop="item.key"
                       :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-cascader
                           v-if="visible"
                           :options="item.options"
                           v-model="form[item.key]"
                           class="m-l5 cascader"
                           :style="{'--style-width':item.width?item.width + 'px':'100%'}"
                           :clearable="item.clearable || false"
                           :props="item.props"
                       />
                   </el-form-item>

                   <!-- 开关  -->
                   <el-form-item
                       v-if="item.type==='switch'"
                       :label="item.label"
                       :label-width="item.labelWidth"
                       :prop="item.key"
                       :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-switch
                           v-model="form[item.key]"
                           class="m-l5"
                           :active-value="item.activeValue || 1"
                           :inactive-value="item.inactiveValue || 0"
                           :active-color="item.activeColor || '#fc702b'"
                           :inactive-color="item.inactiveColor || '#dddfe6'"
                       />
                   </el-form-item>

                   <!-- radio -->
                   <el-form-item
                       v-if="item.type==='radio'"
                       :label="item.label"
                       :label-width="item.labelWidth"
                       :prop="item.key"
                       :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <el-radio-group
                           v-model="form[item.key]"
                           class="ml-5"
                            @change="(e)=>{if(item.fun){item.fun(e)}}"
                       >
                           <el-radio v-for="(val,index) in item.list" :key="index" :label="val.value" size="large">{{val.label}}</el-radio>
                       </el-radio-group>
                   </el-form-item>

                   <!-- 文件类型  -->
                   <el-form-item
                       v-if="item.type==='upload'"
                       :label="item.label"
                       :label-width="item.labelWidth"
                       :prop="item.key"
                       :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <div :style="{width:item.width?item.width + 'px':'100%'}">
                           <FileMinioUpload
                               v-bind="item.interfaceConfig.param"
                               :restriction="true"
                               :restrictionLimit="9"
                               v-model:files="form[item.key]"
                           />
                       </div>
                   </el-form-item>

                   <!-- 自定义类型 -->
                   <el-form-item
                       v-if="item.type==='slot'"
                       :label="item.label"
                       :label-width="item.labelWidth"
                       :prop="item.key"
                       :class="[item.width?'d-flex j-center form-item-center':'']"
                   >
                       <slot :name="item.key" :data="item"></slot>
                   </el-form-item>
               </template>
           </el-form>
       </el-main>
   </template>
  </public-dialog>
</template>

<script setup>
import PublicDialog from "@/components/PublicDialog.vue";
import {nextTick, ref, watch} from "vue";
import {
    ElForm,
    ElFormItem,
    ElInput,
    ElDatePicker,
    ElCascader,
    ElSwitch,
    ElLoading,
    ElMessage
} from "element-plus";
import {
    getInterface,
} from "@/common/utils/GlobalUtils";
import FileMinioUpload from "@/components/FileMinioUpload.vue";

const visible = ref(false);
const isLoading = ref(false);
const props = defineProps({
    popupType:{
      type:String,
      default:'add',
      required:true
    },
    popupParams:{
        type:Object,
        default:{
            width:'50%',
            title:'提示',
            loadingText:'表单数据提交中...',
            footerButton:true,
            confirmButtonTitle:'确认'
        },
    },
    fields:{
        type:Array,
        default:[],
        required:true
    },
    confirmParams:{
        type:Object,
        default:{}
    },
    formParams:{
        type:Object,
        default:{
            formLabelWidth:'100px'
        }
    },
    form:{
        type:Object,
        default:{},
        required:true
    }
});

/**
 * 生成表单验证规则
 * @param data
 * @private
 */
const _initRules = (data) => {
    let rules = {};
    if(!(data instanceof Array)){
        return rules;
    }
    if(data instanceof Array && data.length!==0){
        for (let i = 0; i < data.length; i++){
            rules[data[i].key] = [
                { required: data[i].required===undefined?true:data[i].required, message: data[i].message, trigger: data[i].event },
            ]
        }
        return rules;
    }
}

/**
 * 初始化表单需要的数据
 * @param data
 * @private
 */
const _initData = (data) => {
    if(data instanceof Array && data.length!==0){
        for (let i = 0; i < data.length; i++){
            if(data[i].interfaceConfig!==undefined && (typeof JSON.stringify(data[i].interfaceConfig) !=='{}')){
                if(data[i].options?.list && data[i].options.list.length===0){
                    getInterface(data[i].interfaceConfig.fileName, data[i].interfaceConfig.apiPath, data[i].interfaceConfig.param).then(
                        (res) => {
                            if (res.code === "200") {
                                data[i].options.list = res.data.content===undefined?res.data:res.data.content;
                            }
                        }
                    );
                }
            }
        }
    }
}

/**
 * 生成验证规则
 *
 */
const rules = ref({});
watch(()=>props.fields,(value)=>{
    rules.value =  _initRules(value);
    _initData(value);
    // 此处不应该开启深度监听(deep:true),
    // _initData方法中在调用后台接口请求数据后又对props.fields做了修改(data[i].options.list)
    // ,会导致死循环去调用_initData中的getInterface方法
},{immediate:true});

/**
 * 编辑时回显表单
 * @private
 */
const _initForm = (data,form) => {
    for (let k1 in data){
        for (let k2 in form){
            if(k1 === k2){
                form[k2] = data[k1];
            }
        }
    }
}

/**
 * 弹窗确认
 */
const formRef = ref(null);
const onConfirm = () => {
    formRef.value.validate((valid, fields) => {
        if (valid) {
            if(props.confirmParams.interfaceConfig!==undefined && (typeof JSON.stringify(props.confirmParams.interfaceConfig) !=='{}')){
                isLoading.value = true;
                let params = {
                    ...props.form
                }
                if(props.confirmParams.interfaceConfig.defaultParams!==undefined){
                    params = {
                        ...params,
                        ...props.confirmParams.interfaceConfig.defaultParams
                    }
                }
                getInterface(props.confirmParams.interfaceConfig.fileName, props.confirmParams.interfaceConfig.apiPath,params).then(
                    (res) => {
                        if (res.code === "200") {
                            if(props.confirmParams.fun){
                                props.confirmParams.fun(props.form);
                            }
                            isLoading.value = false;
                            visible.value = false;
                        }else{
                            isLoading.value = false;
                        }
                    }
                );
            }else{
                if(props.confirmParams.fun){
                    props.confirmParams.fun(props.form,isLoading);
                }
            }
        } else {
            console.log('error submit!', fields)
        }
    })
}

/**
 * 文件上传
 * @param file
 * @param item
 */
const uploadFile = (file,item) => {
    let uploadFile = new FormData();
    if(item.interfaceConfig!==undefined){
        uploadFile.append('file', file.file);
        for (let key in item.interfaceConfig.param){
            uploadFile.append(key, item.interfaceConfig.param[key]);
        }
        isLoading.value = true;
        getInterface(item.interfaceConfig.fileName, item.interfaceConfig.apiPath,uploadFile).then(
            (res) => {
                if (res.code === "200") {
                    if(item.interfaceConfig.fun){
                        item.interfaceConfig.fun({fileUrlKey:res.data,item:item,fileName:file.file.name});
                    }else{
                        props.form[item.key] = res.data;
                    }
                    ElMessage.success("上传成功!");
                    isLoading.value = false;
                    formRef.value.clearValidate(item.key);
                }else{
                    ElMessage.error("上传失败!");
                    isLoading.value = false;
                }
            }
        );
    }
};

/**
 * 文件上传
 * @param e
 * @param itemData
 */
const onRemove = (e,itemData) => {
    if(itemData.uploadType === 'Array'){
        props.form[itemData.key].forEach((item,index)=>{
            props.form[itemData.key].splice(index,1);
        });
    }

    if(itemData.uploadType === 'String'){
        props.form[itemData.key] = '';
    }

    if(itemData.uploadType === undefined){
        props.form[itemData.key] = '';
    }
    formRef.value.clearValidate(itemData.key);
}

/**
 * 打开弹窗
 */
const open = (row) => {
    visible.value = true;
    if(props.popupType==='edit'){
        _initForm(row,props.form);
    }
    nextTick(()=>{
        formRef.value.resetFields();
    });
}

/**
 * 关闭弹窗
 */
const close = () => {
    visible.value = false;
}

defineExpose({
    open,
    close
});
</script>

<style lang="scss" scoped>
:deep(.form-item-center) {
    .el-form-item__content{
        flex: none !important;
    }
}
:deep(.el-p .el-input__wrapper) {
    width: var(--style-width) !important;
}
:deep(.date-picker-year) {
    .el-input__wrapper{
        width: var(--style-width) !important;
    }
}
:deep(.cascader) {
    .el-input__wrapper{
        width: var(--style-width) !important;
    }
}
</style>
